package model

import (
	"WebSupervisor/MyTool"
	"WebSupervisor/MyTool/array"
	"WebSupervisor/MyTool/myjson"
	"WebSupervisor/MyTool/set"
	"WebSupervisor/message/cmd"
	"WebSupervisor/message/mail"
	"encoding/json"
	"fmt"
	"strings"
	"time"
)

var smail QQMail
var jobCount int = 0

type JobConfig struct {
	ProjectName    string            `json:"projectName"`
	Header         map[string]string `json:"header"`
	URLs           []URLConfig       `json:"urls"`
	IntervalSecond int               `json:"intervalSecond"`
}
type JobKeyType interface {
	JSONKey | HTMLKey
}

type URLConfig struct {
	URL            string            `json:"url"`
	Output         string            `json:"output"`
	Test           bool              `json:"test"`
	Header         map[string]string `json:"header"`
	Method         string            `json:"method"`
	Body           map[string]string `json:"body"` // 根据实际数据结构调整
	Type           string            `json:"type"` // "json" 或 "html"
	JSONKeys       []JSONKey         `json:"jsonKeys"`
	HTMLKeys       []HTMLKey         `json:"htmlKeys"`
	IntervalSecond int               `json:"intervalSecond"`
}

type JSONKey struct {
	Path []interface{} `json:"path"` // 支持字符串和数字的路径
	Keys []string      `json:"key"`  // 正则表达式字符串
}

type HTMLKey struct {
	Left  string   `json:"left"`
	Right string   `json:"right"`
	Keys  []string `json:"key"` //
}

var Data = DataConfig{}

func ReadJobs(Path string) JobConfig {
	t := MyTool.Read(Path)
	var job JobConfig
	//fmt.Println(">>>ReadJobs:", t)
	err := json.Unmarshal([]byte(t), &job)
	if err != nil {
		fmt.Printf(">>>ReadJobs 转化失败:%v\n", err)
		return JobConfig{}
	}
	return job
}
func (this *JobConfig) InitJobs(mail QQMail) *JobConfig {
	smail = mail
	//将JobConfig中的header添加到URLConfig的header中，不覆盖已有的header
	for i, _ := range this.URLs {
		for k, v := range this.Header {
			if _, ok := this.URLs[i].Header[k]; !ok {
				this.URLs[i].Header[k] = v
			}
		}
		if this.URLs[i].IntervalSecond == 0 {
			this.URLs[i].IntervalSecond = this.IntervalSecond
		}
	}
	fmt.Printf(">>>InitJobs:%#v\n", this)
	return this
}

func (this *JSONKey) superviseKey(myjson *myjson.MyJson, data *JSONData) bool { //匹配返回true
	return MyTool.StringArrayMustCompileStringArray(this.Keys, array.AnyToType[string](this.superviseRefresh(myjson, data)))
}
func (this *JSONKey) superviseRefresh(myjson *myjson.MyJson, data *JSONData) []any { //刷新返回false
	ans := myjson.Gets(this.Path).Ress
	cmd.Log("superviseRefresh data", fmt.Sprintf("%#v", data.Data))
	cmd.Log("superviseRefresh ans", fmt.Sprintf("%#v", ans))

	ref := set.ArrayToSet(ans).Print().Difference(*set.ArrayToSet(data.Data).Print()).ToAnyArray()
	cmd.Log("superviseRefresh ref", fmt.Sprintf("%#v", ref))
	if len(ref) != 0 {
		data.Data = make([]any, len(ans))
		data.Data = ans
		data.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	}
	return ref
}
func (this *HTMLKey) superviseKey(str *string, entry *HTMLData) bool { //匹配返回true
	cmd.Log(">>>superviseKey ", this.Left+" "+this.Keys[0]+" "+this.Right)
	//检查ans中是否存在一个结果与this.Keys中相同的
	return MyTool.StringArrayMustCompileStringArray(this.superviseRefresh(str, entry), this.Keys)
}
func (this *HTMLKey) superviseRefresh(str *string, data *HTMLData) []string { //返回新的内容
	ans := MyTool.GetMid(*str, this.Left, this.Right, 0)
	//如果ans[i]存在于data.Data中，则加入到newans中
	ref := array.AnyToType[string](set.ArrayToSet(array.TypeToAny(ans)).Difference(*set.ArrayToSet(array.TypeToAny(data.Data))).ToAnyArray())
	if len(ref) != 0 {
		data.Data = ans
		data.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
	}
	return ref

}
func (this *URLConfig) superviseJSON(body *myjson.MyJson, entry *DataEntry) bool { //匹配返回true
	if entry.JSONKeys == nil {
		entry.JSONKeys = make(map[any]*JSONData)
	}
	for _, k := range this.JSONKeys {
		ky := fmt.Sprintf("%v", k.Path)
		if _, ok := entry.JSONKeys[ky]; !ok {
			entry.JSONKeys[ky] = new(JSONData)
		}
		if k.superviseKey(body, entry.JSONKeys[ky]) {
			mail.SendMsg(smail.UserName, smail.Password, smail.To, "网页监控匹配成功:"+this.URL, fmt.Sprintf("设置的json key为:%v\n获取到的内容为%v\n", k, entry.JSONKeys[ky]))
			cmd.Print("superviseJSON 匹配成功 this ", *this)
			fmt.Printf(">>>superviseJSON 匹配成功 entry %#v", *entry)
			return true
		}
	}
	return false
}
func (this *URLConfig) superviseHTML(html *string, entry *DataEntry) bool { //匹配返回true
	if entry.HTMLKeys == nil {
		entry.HTMLKeys = make(map[string]*HTMLData)
	}
	for _, k := range this.HTMLKeys {
		key := fmt.Sprintf("[%s,%s,%s]", k.Left, k.Right, k.Keys)
		if _, ok := entry.HTMLKeys[key]; !ok {
			entry.HTMLKeys[key] = new(HTMLData)
		}
		if k.superviseKey(html, entry.HTMLKeys[key]) {
			mail.SendMsg(smail.UserName, smail.Password, smail.To, "网页监控匹配成功:"+this.URL, fmt.Sprintf("设置的json key为:%v\n获取到的内容为%v\n", k, entry.JSONKeys[key]))
			cmd.Print(">>>superviseJSON 匹配成功", *this)
			return true
		}
	}
	return false
}

func (this *URLConfig) supervise(entry *DataEntry) {
	var res string
	FuncSupervise := func() {
		for {
			cmd.Log("URLConfig Supervise", this)
			//获取数据
			switch strings.ToUpper(this.Method) {
			case "POST":
				res = MyTool.NewHttpHeader(this.URL, this.Header).Post(this.Body).Read().GetBodyString()
				break
			case "GET":
				res = MyTool.NewHttpHeader(this.URL, this.Header).Get("").Read().GetBodyString()
				break
			}
			if this.Output != "" && this.Test {
				cmd.Log(">>>superviseJSON 写入文件 output", this.Output)
				MyTool.Write(this.Output, res)
				//jobCount--
				return
			} else {
				if myjson.CanConvert(res) && len(this.JSONKeys) != 0 { //监督数据
					this.superviseJSON(myjson.NewJsons(res), entry)
				} else {
					this.superviseHTML(&res, entry)
				}
				time.Sleep(time.Second * time.Duration(this.IntervalSecond))
			}
		}
	}
	FuncSupervise()
	//go FuncSupervise()
}
func (this *JobConfig) Supervise() {
	Data.Datas = make(map[string]*DataEntry)
	jobCount = len(this.URLs)
	for _, v := range this.URLs {
		Data.Datas[v.URL] = new(DataEntry)
		go v.supervise(Data.Datas[v.URL])
	}
	for {
		if jobCount == 0 {
			break
		}
		time.Sleep(time.Second * 10)
	}
}
